package com.soul.server.server;

import com.alibaba.fastjson.JSON;
import com.soul.autoconfig.template.HuanXinTemplate;
import com.soul.commons.constans.Constants;
import com.soul.commons.exception.SoulGlobalException;
import com.soul.dubbo.api.db.QuestionsApi;
import com.soul.dubbo.api.db.UserApi;
import com.soul.dubbo.api.db.UserInfoApi;
import com.soul.dubbo.api.mongo.RecommendUserApi;
import com.soul.dubbo.api.mongo.UserLikeApi;
import com.soul.dubbo.api.mongo.UserLocationApi;
import com.soul.dubbo.api.mongo.VisitorApi;
import com.soul.model.db.Question;
import com.soul.model.db.User;
import com.soul.model.db.UserInfo;
import com.soul.model.mongo.RecommendUser;
import com.soul.model.mongo.UserLike;
import com.soul.model.mongo.Visitors;
import com.soul.model.vo.*;
import com.soul.server.utils.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author mdoya
 * @version 1.0
 * @description:
 */
@Slf4j
@Service
public class SoulService {

    @DubboReference
    private UserApi userApi;

    @DubboReference
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private QuestionsApi questionsApi;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @DubboReference
    private UserLocationApi userLocationApi;

    @DubboReference
    private UserLikeApi userLikeApi;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @DubboReference
    private VisitorApi visitorApi;

    @Value("${soul.default.recommend.users}")
    private String recommendUserIds;

    /**
     * 今日佳人
     *
     * @return todayBestVo
     */
    public TodayBestVo findTodayBest() {
        // 根据登录用户id查询  今日佳人用户id
        Long userId = UserHolder.getUserId();
        RecommendUser recommendUser = recommendUserApi.findTodayBestByRecommendUser(UserHolder.getUserId());
        // 没有今日佳人recommendUser对象数据  模拟客服是今日佳人
        if (recommendUser == null) {
            recommendUser = new RecommendUser();
            recommendUser.setUserId(userId % 99 + 1);
            recommendUser.setScore(88d);
        }
        // 今日佳人用户id拿到用户数据
        UserInfo userInfo = userInfoApi.findByUserIdUser(recommendUser.getUserId());
        return TodayBestVo.init(userInfo, recommendUser);
    }

    /**
     * 首页推荐佳人分页列表
     *
     * @return todayBestVo 接受前端参数
     */
    public PageResult<TodayBestVo> findpageRecommendation(RecommendUserVo recommendUserVo) {
        // 当前登录用户id
        Long userId = UserHolder.getUserId();
        // MongoDB 根据登录用户id查询今日佳人用户匹配度最佳   这里的数据来源MongoDB大数据分析  目标拿到今日佳人用户ids
        PageResult<RecommendUser> recommendUserList = recommendUserApi.findpageRecommendation(recommendUserVo, userId);
        // 今日佳人用户id和匹配度
        List<RecommendUser> listItems = recommendUserList.getItems();
        // 模拟造数据 客服
        if (recommendUserList.getPage() > 0 && CollectionUtils.isEmpty(listItems)) {
            recommendUserList.setItems(getDefaultRecommendUserList());
            recommendUserList.setCounts(10L);
            recommendUserList.setPage(1L);
        }
        // 封装Vo数据给前端
        List<TodayBestVo> todayBestVos = new ArrayList<>();
        // 根据用户id拿到详细信息
        if (!CollectionUtils.isEmpty(listItems)) {
            // 拿到所有佳人用户ids
            List<Long> ids = listItems.stream().map(RecommendUser::getUserId).collect(Collectors.toList());
            // 佳人用户分页信息
            if (ids.size() > 0) {
                // 用户详细信息
                Map<Long, UserInfo> userInfoMap = userInfoApi.findIdsUserInfoList(ids);
/*                for (RecommendUser recommendUser : listItems) {
                    UserInfo userInfo = userInfoMap.get(recommendUser.getUserId());
                    if (userInfo != null) {
                        todayBestVos.add(TodayBestVo.init(userInfo, recommendUser));
                    }
                }*/

                todayBestVos = listItems.stream().map((item) -> {
                    UserInfo userInfo = userInfoMap.get(item.getUserId());
                    TodayBestVo todayBestVo = null;
                    if (userInfo != null) {
                        todayBestVo = TodayBestVo.init(userInfo, item);
                    }
                    return todayBestVo;
                }).collect(Collectors.toList());
            }
        }
        return new PageResult<>(recommendUserList.getPage(), recommendUserList.getPagesize(), recommendUserList.getCounts(), todayBestVos);
    }

    /**
     * 默认客服
     *
     * @return
     */
    private List<RecommendUser> getDefaultRecommendUserList() {
        List<RecommendUser> list = new ArrayList<>();
        // 随机产生开始的客户id, 从这个客服的id开始，往后取10个
        int startIndex = RandomUtils.nextInt(1, 90);
        RecommendUser recommendUser = null;
        for (long i = startIndex; i < startIndex + 10; i++) {
            recommendUser = new RecommendUser();
            recommendUser.setUserId(i);
            recommendUser.setScore(RandomUtils.nextDouble(70, 88));
            list.add(recommendUser);
        }
        return list;
    }

    /**
     * 根据佳人id查询佳人信息
     *
     * @param id 佳人id
     * @return ResponseEntity
     */
    public TodayBestVo findPersonalInfo(String id) {
        Long personUserId = Long.valueOf(id);
        Long currendUserId = UserHolder.getUserId();
        // 1. 查询佳人信息
        UserInfo userIdUser = userInfoApi.findByUserIdUser(personUserId);

        // 2. 佳人佳人缘分值
        RecommendUser recommendUser = recommendUserApi.findByUser(currendUserId, personUserId);
        // 2.1 缘分值为空则造数据
        if (recommendUser == null) {
            recommendUser = new RecommendUser();
            recommendUser.setUserId(currendUserId);
            recommendUser.setScore(Double.valueOf(65 + currendUserId % 10));
        }
        // 2.2 添加用户访问记录(我的访问记录)
        Visitors visitors = new Visitors();
        visitors.setUserId(personUserId); // 被访问用户id
        visitors.setVisitorUserId(currendUserId); // 访问用户id
        visitors.setFrom("首页");
        visitors.setScore(recommendUser.getScore());
        visitorApi.addVisitors(visitors);

        TodayBestVo.init(userIdUser, recommendUser);
        return TodayBestVo.init(userIdUser, recommendUser);
    }

    /**
     * 即时通讯-查询陌生人问题
     *
     * @param userId 佳人id
     * @return 字符串
     */
    public String findStrangerQuestions(Long userId) {
        Question question = questionsApi.findQuestionById(userId);
        if (question != null) {
            return question.getTxt();
        }
        return "为什么要喜欢我!";
    }

    /**
     * 即时通讯-回复陌生人问题(发布陌生人问题)
     * {
     * "userId": 106,
     * "huanXinId": "hx106",
     * "nickname": "黑马小妹",
     * "strangerQuestion": "你喜欢去看蔚蓝的大海还是去爬巍峨的高山？",
     * "reply": "我喜欢秋天的落叶，夏天的泉水，冬天的雪地，只要有你一切皆可~"
     * }
     *
     * @param beautyUserId 佳人id
     * @param reply        陌生人问题
     * @return null
     */
    public void addStrangerQuestions(Long beautyUserId, String reply) {
        // 1. 根据佳人id查询用户信息表
        User u = userApi.findById(beautyUserId);
        // 2. 当前登录用户信息
        User user = UserHolder.getUser();
        // 3. 当前登录用户详细信息
        Long userId = user.getId();
        UserInfo userInfo = userInfoApi.findByUserIdUser(userId);
        // 4. 查询陌生人问题 抽取公共方法

        Map<String, Object> map = new HashMap<>();
        map.put("userId", userId);
        map.put("huanXinId", user.getHxUser());
        map.put("nickname", userInfo.getNickname());
        map.put("strangerQuestion", strangerQuestions(beautyUserId));
        map.put("reply", reply);
        if (!huanXinTemplate.sendMsg(u.getHxUser(), JSON.toJSONString(map))) {
            throw new SoulGlobalException(ErrorResult.error());
        }
    }

    /**
     *  查询陌生人问题
     */
    public String strangerQuestions(Long userId) {
        //1.根据当前用户id查询tb_question表 获取陌生人问题
        Question question = questionsApi.findQuestionById(userId);
        if(question != null && StringUtils.isNotEmpty(question.getTxt())){
            return question.getTxt();
        }
        return "约嘛?";
    }

    /**
     *   搜索附近的人
     * @param gender 性别
     * @param distance 搜索范围 单位：米
     * @return List<NearUserVo>
     */
    public List<NearUserVo> searchNearBy(String gender, Long distance) {
        // 1. 拿到当前用户地址位置  并且拿到附近好友的ids
        List<Long> userIdsList = userLocationApi.searchNearBy(UserHolder.getUserId(),distance);
        // 2. 附近人ids获取对应userinfo表详细信息 userIdsList不会为空，至少有自己
        UserInfo userInfoCondition = new UserInfo();
        userInfoCondition.setGender(gender);
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIdsAndCondition(userIdsList, userInfoCondition);
        // 3. 构造Vo数据返回
        List<NearUserVo> nearUserVoList = new ArrayList<>();
        for (Long key : userIdsList) {
            if (userInfoMap != null){
                UserInfo userInfo = userInfoMap.get(key);
                if (userInfo != null){
                    nearUserVoList.add(NearUserVo.init(userInfo));
                }
            }
        }
        return nearUserVoList;
    }

    /**
     *  探花 - 查询卡片分页列表
     * @return List<TodayBestVo>
     */
    public List<TodayBestVo> findCards() {
        Long currendUserId = UserHolder.getUserId();
        // 1. 查询推荐系统卡片分页列表
        List<RecommendUser> recommendUserList = new ArrayList<>();
                recommendUserList = recommendUserApi.findCards(currendUserId);

        // 2. 模拟数据
        if (CollectionUtils.isEmpty(recommendUserList)){
            for (String recommendUserId : recommendUserIds.split(",")) {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setUserId(currendUserId);
                recommendUser.setToUserId(Long.valueOf(recommendUserId));
                recommendUser.setScore(RandomUtils.nextDouble(70,80));
                recommendUserList.add(recommendUser);
            }
        }
        // 2.2 推荐系统集合获取用户ids
        List<Long> recommendUserIds = recommendUserList.stream().map(RecommendUser::getUserId).collect(Collectors.toList());
        // 3. 根据推荐id查询用户详细信息
        List<TodayBestVo> todayBestVoList = new ArrayList<>();
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(recommendUserIds);
        for (RecommendUser recommendUser : recommendUserList) {
            if (userInfoMap != null){
                UserInfo userInfo = userInfoMap.get(recommendUser.getUserId());
                if (userInfo != null){
                    todayBestVoList.add(TodayBestVo.init(userInfo,recommendUser));
                }
            }
        }
        return todayBestVoList;
    }

    /**
     *  探花-喜欢与不喜欢
     * @param likeUserid 佳人id
     */
    public void love(Long likeUserid,boolean flag) {
        User user = UserHolder.getUser();
        Long currendUserId = user.getId();
        // 1.查询当前用户user_like集合 喜欢与不喜欢
        UserLike userLike = new UserLike();
        userLike.setUserId(currendUserId);
        userLike.setLikeUserId(likeUserid);
        userLike.setIsLike(flag);
        // islive返回值双向奔现
        Boolean islive = userLikeApi.love(userLike);

        String liveKey = Constants.USER_LIKE_KEY + currendUserId;
        String unLiveKey = Constants.USER_LIKE_KEY + currendUserId;
        if (flag){// 2. 喜欢
            stringRedisTemplate.opsForSet().add(liveKey,likeUserid.toString());
            stringRedisTemplate.opsForSet().remove(unLiveKey,likeUserid.toString());
        } else { // 3. 不喜欢
            stringRedisTemplate.opsForSet().remove(liveKey,likeUserid.toString());
            stringRedisTemplate.opsForSet().add(unLiveKey,likeUserid.toString());
        }
        // 4. 双向奔现
        if (islive){
            // 5. 添加环信账号
            if (!huanXinTemplate.addContact(user.getHxUser(),userApi.findById(likeUserid).getHxUser())){
                throw new SoulGlobalException(ErrorResult.error());
            }
        }



    }
}
